(function($, undefined) {

var has_placeholder = ("placeholder" in document.createElement("input"));

$.fn.prettify = function(options) {
	var settings = $.extend({
		prepend: 'prettify_',
		type: 'default'
	}, options || {});

	return this.each(function() {
		var $this = $(this);

		if ( $this.is('.' + settings.prepend + '_ed') ) {
			return;
		} else {
			$this.addClass(settings.prepend + '_ed');
		}

		if ( this.type == 'select-one' ) {
			$.prettify.select(this, settings);
		} else if ( this.type == 'select-multiple' ) {
			$.prettify.select_multiple(this, settings);
		} else if ( this.type == 'email' || this.type == 'text' || this.type == 'password' ) {
			$.prettify.text(this, settings);
		}
	});
};

$.prettify = {
	text: function(element, settings) {
		var $wrapper = $('<span/>');
		var $input = $(element);
		var prepend = settings.prepend;
		var $placeholder;

		$wrapper
			.addClass(prepend + 'input')
			.addClass(prepend + 'text')
			.addClass(prepend + 'wrapper')
			.css({
				position: 'relative'
			});

		/* cheat placeholder in inputs for lolexplorer */
		if ( !has_placeholder ) {
			$placeholder = $('<span/>');

			$placeholder
				.bind('click', function() {
					$input.focus();
				})
				.css({
					opacity: .5,
					display: 'block'
				})
				.addClass(prepend + 'placeholder')
				.attr({'for': this.id})
				.text($input.attr('placeholder'));

			if ( $input.val() != '' ) $placeholder.hide()

			$input
				.bind('focus', function() {
					$placeholder.hide();
				})
				.bind('blur', function() {
					if ( $input.val() == '' ) $placeholder.show();
				});

			$wrapper.append($placeholder);
		}

		$wrapper.insertAfter($input);
		$wrapper.prepend($input);

		if ( !has_placeholder ) {
			var offset = $input.position();
			var offset_left = (parseInt($input.css('borderLeftWidth')) || 0) + (parseInt($input.css('paddingLeft')) || 0) + (parseInt($input.css('marginLeft')) || 0);
			var offset_top = (parseInt($input.css('borderTopWidth')) || 0) + (parseInt($input.css('paddingTop')) || 0) + (parseInt($input.css('marginTop')) || 0);

			$placeholder.css({
				position: 'absolute',
				left: offset.left + offset_left,
				top: offset.top + offset_top
			});
		}
	},
	select: function(element, settings) {
		var $wrapper = $('<span/>');
		var $value = $('<span/>');
		var $input = $(element);
		var prepend = settings.prepend;

		$value
			.addClass(prepend + 'value')
			.css({
				display: 'block',
				overflow: 'hidden',
				textOverflow: 'ellipsis',
				whiteSpace: 'nowrap'
			});

		$wrapper
			.addClass(prepend + 'input')
			.addClass(prepend + 'select')
			.addClass(prepend + 'wrapper')
			.css({
				position: 'relative',
				display: 'inline-block'
			});

		var val = element.options[element.selectedIndex].innerHTML;
		if ( val == '' ) val = '&nbsp;';

		$wrapper.insertAfter($input);

		$value.html(val);
		$wrapper.append($value);
		$wrapper.append($input);

		var input_outer_width = $input.outerWidth();
		var input_inner_width = $input.width();
		var wrapper_inner_width = $wrapper.width();

		if ( wrapper_inner_width > input_outer_width ) $input.width(wrapper_inner_width);

		$wrapper.css({width: $wrapper.width()});

		$input
			.css({
				opacity: 0,
				position: 'absolute',
				left: 0,
				bottom: 0
			})
			.bind('change keyup', function() {
				var option = this.options[this.selectedIndex];
				$value.html(option.innerHTML);
			})
			.bind('focus', function() {
				$value.addClass('focus');
			})
			.bind('blur', function() {
				$value.removeClass('focus');
			});

		var input_outer_height = $input.outerHeight();
		var input_inner_height = $input.height();
		var wrapper_inner_height = $wrapper.height();

		if ( wrapper_inner_height > input_outer_height ) $input.height(wrapper_inner_height);
	},
	select_multiple: function(element, settings) {
		var $input = $(element);
		var options = element.options;
		var $wrapper = $('<span/>');
		var $values_wrapper = $('<ul/>');
		var $dropdown = $('<select/>');
		var opts = [];
		var prepend = settings.prepend;

		$input
			.attr({
				tabIndex: -1
			})
			.css({
				opacity: 0,
				position: 'absolute',
				left: '-9000px'
			});

		$wrapper
			.addClass(prepend + 'input')
			.addClass(prepend + 'select_multiple')
			.css({
				position: 'relative',
				/*overflow: 'hidden',*/
				display: 'inline-block'
			});

		var $first_option = $('<option/>');

		if ( $input.attr('data-placeholder') ) {
			$first_option.html($input.attr('data-placeholder'));
		} else {
			$first_option.html('Selections:');
		}

		$dropdown.append($first_option);
		$first_option
			.attr({
				disabled: 'disabled'
			});

		for ( var i=0, opt; (opt = options[i]); i++ ) {
			var $option = $('<option/>');
			$option.html(opt.innerHTML);

			$dropdown.append($option);

			opts[i] = {
				$option: $option,
				option: opt
			};
		}

		var add_option = function(opt) {
			if ( !opt ) return;
			$dropdown[0].options[0].selected = true;

			if ( $.browser.msie && $.browser.version < 8 && opt.option.selected ) {
				return;
			}

			opt.option.selected = true;

			opt.$option
				.css({display: 'none'})
				.attr({disabled: 'disabled'});


			var $value = $('<li/>')
			$value
				.addClass(prepend + 'value')

			var $text = $('<span/>');
			$text
				.addClass(prepend + 'text')
				.html(opt.option.innerHTML);

			var $remove = $('<a href="#"/>');
			$remove
				.addClass(prepend + 'remove')
				.html('(remove)');

			$value
				.append($text)
				.append($remove);

			$values_wrapper.append($value);

			$remove
				.bind('click', function(e) {
					e.preventDefault();
					opt.option.selected = false;
					$value.empty().remove();
					opt.$option
						.css({display: 'block'})
						.removeAttr('disabled');

					if ( $.browser.msie && $.browser.version < 8 ) {
						opt.$option.parent().insertAfter(opt.$option).detatch();
					}

					if ( !$values_wrapper.children().length ) $values_wrapper.hide();
				});

			$values_wrapper.show();
		};

		$dropdown
			.bind('change', function(e) {
				var el = e.srcElement || e.target;
				var opt = opts[el.selectedIndex - 1];
				add_option(opt);
			});

		$wrapper.insertAfter($input);
		$wrapper.append($input);
		$wrapper.append($values_wrapper);
		$wrapper.append($dropdown);

		$dropdown.prettify(settings);
		$values_wrapper.hide();

		for ( var i=0, opt; (opt = opts[i]); i++ ) {
			if ( opt.option.selected ) {
				add_option(opt);
			}
		}
	}
};

})(jQuery);